#include "testfunctions.h"
void testAdventurer(struct gameState* state){
    
    int preHandTreasure = numTreasure(state);
    int numErrors = 0;
    int player = whoseTurn(state);
    int preCount = state->handCount[player];
    int hpos;
    int i;
	for (i = 0; i < state->handCount[player]; i++)
	{
        if (state->hand[player][i] == adventurer)
            hpos=i;
    }
    cardEffect(adventurer,0,0,0,state,hpos,0);
    if(preHandTreasure>=2){
        if(state->handCount[player]!=preCount+2){
            printf("Failed to draw 2 treasure cards correctly, number of cards in hand is: %i\n",state->handCount[player]);
            numErrors++;
        }
        else{
            if(numTreasure(state)!=preHandTreasure-2){
                printf("Failed to decrement our treasure count correctly number of treasure cards in hand: %i\n",numTreasure(state));
                numErrors++;
            }
            else{
                printf("no errors in card numbers changing at least\n");
            }
        }
    }
    else{
        if(state->handCount[player]!=preCount+preHandTreasure){
            printf("Failed to draw %i treasure cards correctly, number of cards in hand is: %i\n",preHandTreasure,state->handCount[player]);
            numErrors++;
        }
        else{
            if(numTreasure(state)!=numTreasure(state)-preHandTreasure){
                printf("Failed to decrement our treasure count correctly number of treasure cards in hand: %i\n",numTreasure(state));
                numErrors++;
            }
            else{
                printf("no errors in card numbers changing at least\n");
            }
        }
    }
    printf("Number of errors during run of testAdventurer() %i\n",numErrors);
}
void  testMinion(struct gameState *state) {
    int i;
int player = whoseTurn(state);
int prenumActions , postnumActions, precoins, postcoins ;

prenumActions = state->numActions;
precoins=state->coins;
int  hpos;

	for (i = 0; i < state->handCount[player]; i++)
	{
	  if (state->hand[player][i] == minion)
	       hpos=i;			// minion card position in player hand
	 	}
	playCard(hpos,1,0,0,state);

postnumActions = state->numActions;
postcoins=state->coins;

//assert (prenumActions+1==postnumActions);
	printf("Success test:  number of actions after playing action phase with minion card  \n");

//assert (precoins+1==postcoins);
	printf("Success test:  number of actions after playing action phase with minion card  \n");

}


void  testBaron(struct gameState *state) {
    int i;
int player = whoseTurn(state);
int prenumBuys, postnumBuys;

prenumBuys=state->numBuys;

int  hpos;

	for (i = 0; i < state->handCount[player]; i++)
	{
	  if (state->hand[player][i] == baron)
	       hpos=i;			// baron card position in player hand
	 	}
	playCard(hpos, rand()%2,0,0,state);

postnumBuys=state->numBuys;

assert (prenumBuys+1==postnumBuys);
	printf("Success test:  number of buys after playing action phase with baron card  \n");

}



void  testVillage(struct gameState *state) {
    int i ;
int player = whoseTurn(state);
int prenumActions , postnumActions ;

prenumActions = state->numActions;
int hpos;

	for (i = 0; i < state->handCount[player]; i++)
	{
	  if (state->hand[player][i] == village)
	       hpos=i;			// village card position in player hand
	 	}
	 playCard(hpos, 0,0,0, state);

postnumActions = state->numActions;

assert (prenumActions+2==postnumActions);
	printf("Success test:  number of actions increases by 2 after action phase with village card is completed  \n");

}



void  testSmithy(struct gameState *state) {

int player = whoseTurn(state);
int prehandCount, posthandCount;

prehandCount = state->handCount[player];
int  hpos;
    int i;
	for (i = 0; i < state->handCount[player]; i++)
	{
	  if (state->hand[player][i] == smithy)
	       hpos=i;			// smithy card position in player hand
	 	}
  playCard(hpos, 0, 0, -1, state);

posthandCount = state->handCount[player];

assert (posthandCount==prehandCount+2);
	printf("Success test:  player hand count is 2 cards more after playing smithy card  \n");

}



void  testRemodel(struct gameState *state) {

int player = whoseTurn(state);
int presum, postsum,prediscardCount;

prediscardCount = state->discardCount[player];

presum  = state->handCount[player] + state->discardCount[player] ;
    int j = 0;
int ch1=0, hpos,i;
	for ( i = 0; i < state->handCount[player]; i++)
	{
	  if (state->hand[player][i] == remodel)
	       hpos=i;			// remodel card position in player hand
    }
    for(i = 0; i < hpos;i++){
        if (state->hand[player][i]!=-1) {
            ch1 = i;
            break;
        }
    }
    for(j = adventurer; j > treasure_map;j++){
        if(state->supplyCount[j]>0)
            break;
    }
    if(playCard(hpos, ch1, j, -1, state) >=0){
        postsum  = state->handCount[player] + state->discardCount[player] ;
        printf("%i %i \n",presum,postsum);
       // assert (presum==postsum);
        printf("Success test:  for remodel  \n");
    }
    else{
        printf("Unable to play card due to an error in play.\n");
    }

}

void  testMine(struct gameState *state) {

int player = whoseTurn(state);
int prediscardCount, postdiscardCount;
    int i;
prediscardCount = state->discardCount[player];
int ch1,ch2, hpos;
for (i = 0; i < state->handCount[player]; i++) {
            if (handCard(i, state) == copper)
              {  ch1=5;   //copper card position
				ch2=6;		// silver card position
				}
            else if (handCard(i, state) == silver)
                { ch1 =6;  // silver card position
				  ch2 =7;  // gold card position
                }
		}

	for (i = 0; i < state->handCount[player]; i++)
	{
	  if (state->hand[player][i] == mine)
	       hpos=i;			// mine card position in
	 	}
			 playCard(hpos, ch1, ch2, -1, state);

postdiscardCount = state->discardCount[player];

//assert (prediscardCount+2==postdiscardCount);
	printf("Success test:  discarded pile is 2 cards more after playing mine  \n");

}



void testFeast(struct gameState *state) {

	int player = whoseTurn(state);
	int predeckCount, postdeckCount, prediscardCount, postdiscardCount;
    int i;

	prediscardCount = state->discardCount[player];
	predeckCount = state->deckCount[player];
    int ch1=0;
    for (i = adventurer; i < treasure_map; i++) {
        if (state->supplyCount[i]>1 && state->coins > getCost(state->supplyCount[i])) {
            ch1 = i;
            break;
        }
    }
    int result = cardEffect(feast, ch1, -1, -1, state, 0, 0);
    if(result!=-1){
	postdiscardCount = state->discardCount[player];
	postdeckCount = state->deckCount[player];
	//assert (prediscardCount+1 == postdiscardCount);
	printf("Success test: this card is trashed for player [ %d ]  \n",player);
	//assert (predeckCount+1==postdeckCount);
	printf("Success test:  gained a card   \n");
    }
}

void  testCouncilRoom(struct gameState *state) {
    int i;
int player = whoseTurn(state);
int preBuys = state->numBuys;
int preHandCount[6];
int postHandCount[6];


    for(i=0; i<state->numPlayers;i++){
		   preHandCount[i]=state->handCount[i];
	   }
    

     int results= cardEffect(council_room, -1, -1, -1, state, 0, 0);
    if(results ==-1){
        return;
    }
    for(i=0; i<state->numPlayers;i++){
		   postHandCount[i]=state->handCount[i];
	   }
    for (i = 0; i < state->numPlayers; i++) {
        if(i == player){
            assert (state->handCount[player] == (preHandCount[player]+3));
            printf("Success test: 4 cards added to hand player [ %d ]  \n",player);
        }
        else{
            assert (state->handCount[i]==(preHandCount[i]+1));
            }
        }
    printf("Success test:  Each other player draws a card    \n");
    printf("number of players in game: %i\n",state->numPlayers);
    printf("number of buys before: %i after:%i\n",preBuys,state->numBuys);
    
  assert (state->numBuys>(preBuys));
  printf("Success test:  total numBuys updated correctly    \n");
}


void testGreatHall(struct gameState* state){
    int player = whoseTurn(state);
    int preCount = state->handCount[player];
    int preActions = state->numActions;
    int result,hpos;
    int bonus = 0;
    int failed_tests = 0;
    int i;

	for (i = 0; i < state->handCount[player]; i++)
	{
	  if (state->hand[player][i] == minion)
	       hpos=i;			// GreatHall card position in player hand
	 	}

    result = cardEffect(great_hall,0,0,0,state,1,&bonus);
    if (result !=0 || state->handCount[player]!=preCount) {
        printf("Failed card count test for great hall for player %i\n",player);
        failed_tests+=1;
    }
    if (preActions+1 != state->numActions){
        printf("Failed action increment test for great hall for player %i\n",player);
        failed_tests+=1;
    }
    if(failed_tests==0){
        printf("All tests for great hall passed\n");
    }
    else{
        printf("Number of tests failed for great hall is %i\n",failed_tests);
    }
}

void testSteward(struct gameState* state, int player){
    int failed_tests = 0;
    int result;
    int bonus = 0;
    int preCount = state->handCount[player];
    //basic steward case, draw two cards for player
    result = cardEffect(steward,1,0,0,state,1,&bonus);
    if(result !=0 ||preCount==state->handCount[player] ){
        printf("Failed test for drawing two cards for steward for player %i \n",player);
        failed_tests+=1;
    }
    //add two coins case
    int preCoins = state->coins;
    result = cardEffect(steward,2,0,0,state,1,&bonus);
    if(result!=0 || preCoins+2 !=state->coins){
        printf("Failed test for adding two coins for player %i \n",player);
        failed_tests+=1;
    }
    //trash 2 cards case
    int preHandCount = state->handCount[player];
    result = cardEffect(steward,3,0,state->handCount[player]-1,state,1,&bonus);
    //3 cards in total must be discarded for steward to be appeased
    if(result !=0 || preHandCount-3 !=state->handCount[player]){
        printf("Failed test for discard state for player %i \n",player);
        failed_tests+=1;
    }
    if(failed_tests==0){
        printf("All tests for steward card passed.\n");
    }
    else{
        printf("Number of failed tests for the steward card is: %i.\n",failed_tests);
    }
}


void testOutpost(int handPos, struct gameState* state){
    int turn = whoseTurn(state);
    int currOutpost = state->outpostPlayed;
    state->hand[turn][handPos]=outpost;
    cardEffect(outpost,0,0,0,state,handPos,0);
    if(currOutpost+1 != state->outpostPlayed){
        printf("Number of outpost cards failed to increment\n");
    }
    endTurn(state);
    if( turn != whoseTurn(state)){
        printf("Outpost failed to maintain current player's turn\n");
    }
    else{
        if(state->handCount[turn]!=3){
            printf("Outpost turn not implemented correctly, number of cards in hand is: %i\n",state->handCount[turn]);
        }
    }
}


void testSalvager(struct gameState* state){
    int failed_tests = 0;
    int player = whoseTurn(state);
    int result;
    int preBuys = state->numBuys;
    int preCoins = state->coins;
    int preHandCount = state->handCount[player];
    int bonus = 0;
    int preValue = getCost(handCard(1,state));
    
    result = cardEffect(salvager,1,0,0,state,0,&bonus);
    if(result !=0 || preCoins+preValue != state->coins){
        printf("Failed on trash and coin gain test on player %i for salvager \n",player);
        failed_tests+=1;
    }
    //two cards must be gone for this particular state to pass, as it shall be done.
    if(preHandCount-2!=state->handCount[player]){
        printf("Failed to discard card as a part of coin gain for player %i for salvager \n",player);
        failed_tests+=1;
    }
    preHandCount = state->handCount[player];
    preBuys= state->numBuys;
    result = cardEffect(salvager,0,0,0,state,0,&bonus);
    if(preBuys+1!=state->numBuys){
        printf("Failed to increment buys on subsequent use of salvager for player %i \n",player);
        failed_tests+=1;
    }
    
    if(state->handCount[player]>=preHandCount){
        printf("Failed to discard card for use of salvager for player %i \n",player);
        failed_tests+=1;
    }
    if(failed_tests==0){
        printf("All tests passed for salvager card \n");
    }
    else{
        printf("Number of tests that failed for salvager card: %i\n",failed_tests);
    }
}
void testSeaHag(struct gameState* state){
    int i;
    int currentPlayer = whoseTurn(state);
    int hpos = 0;
    for(i = 0; i < state->handCount[currentPlayer];i++){
        if(state->hand[currentPlayer][i] == sea_hag){
            hpos = i;
            break;
        }
    }
    int funcResult = cardEffect(sea_hag,0,0,0,state,hpos,0);
    if (funcResult>=0) {
        for(i = 0; i < state->numPlayers;i++)
            if(i!=currentPlayer){
                //assert(state->deck[i][state->deckCount[i]-1]==curse);
                
            }
    }
}
void testGardens(struct gameState* state){
    int i;
    int currentPlayer = whoseTurn(state);
    int hpos = 0;
    for(i = 0; i < state->handCount[currentPlayer];i++){
        if(state->hand[currentPlayer][i]==gardens){
            hpos=i;
            break;
        }
    }
    int testResult = cardEffect(gardens,0,0,0,state,hpos,0);
    assert(testResult == -1);
}

